package com.so206.controller.pay;

import com.alibaba.fastjson.JSON;
import com.so206.controller.pay.process.NotifyThread;
import com.so206.controller.pay.process.UserBalnesChange;
import com.so206.controller.pay.process.VipModePayProcess;
import com.so206.controller.pay.process.VipNotifyProcess;
import com.so206.plugins.pay.AliPayFunction;
import com.so206.plugins.pay.WxPayFunction;
import com.so206.plugins.pay.YiPayFunction;
import com.so206.po.*;
import com.so206.po.ext.CodePayRetBean;
import com.so206.service.*;
import com.so206.utils.HttpClientUtils;
import com.so206.utils.PayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

@Controller
@RequestMapping({"/payment"})
public class CodePayController {
    private static Logger logger = LoggerFactory.getLogger(CodePayController.class);
    @Autowired
    private YiPayFunction yiPayFunction;
    @Autowired
    private OrderService orderService;
    @Autowired
    private WebConfigService webConfigService;
    @Autowired
    private UserBalnesChange userBalnesChange;
    @Autowired
    private VipService vipService;
    @Autowired
    private SettLementService settLementService;
    @Autowired
    private UserService userService;
    @Autowired
    private WxPayFunction wxPayFunctionPC;
    @Autowired
    private AliPayFunction aliPayFunction;
    @Autowired
    private PayConfigService payConfigService;
    @Autowired
    private WxPayConfigService wxPayConfigService;
    @Autowired
    private AlipayConfigService alipayConfigService;
    @Autowired
    private CodePayConfigService codePayConfigService;

    @Autowired
    private ProxyService proxyService;

    /**
     * 码支付 -- 支付
     */
    @RequestMapping({"/code_pay"})
    public String codePay(Model model, Long id) throws Exception {
        SystemWeb web = this.webConfigService.find_by_id(1L);
        SystemPayConfig config = this.payConfigService.getPayConfig(1L);
        model.addAttribute("config", web);
        SystemOrder order = this.orderService.findOrderById(id);
        if (order == null) {
            throw new Exception("订单id错误,请返回重试!");
        } else if (order.getStatus() == 2) {
            throw new Exception("订单已支付,请勿重复发起支付请求!");
        } else {
            CodepayConfig code = codePayConfigService.find_by_id(order.getPayConnet());
            LinkedHashMap<String, String> map = new LinkedHashMap<>();
            map.put("id", code.getPid());
            map.put("type", String.valueOf(PayUtils.switch_pay_type_code_pay(order.getPayType())));
            map.put("price", String.valueOf(order.getPrice().subtract(order.getSaleMonney())));
            map.put("pay_id", order.getOutOrderId());
            map.put("page", "4");
            map.put("notify_url", config.getRetDomain() + "/payment/code_pay_notify2");
            map.put("return_url", web.getHttpUrl() + "/payment/return_page");
            map.put("sign", this.yiPayFunction.buildRequestMysign2(map, code.getPublicKeyMch()));
            String ret = HttpClientUtils.get(code.getUrl() + "?" + this.yiPayFunction.createLinkString(map));
            model.addAttribute("ret_str", ret);
            CodePayRetBean bean = JSON.parseObject(ret, CodePayRetBean.class);
            model.addAttribute("model", bean);
            model.addAttribute("return_url", web.getHttpUrl() + "/payment/return_page?out_trade_no=" + order.getOutOrderId());
            return "pay/code_pay_" + order.getPayType();
        }
    }

    /**
     * 码支付回调2
     */
    @RequestMapping("/code_pay_notify2")
    public void codepay_notify(HttpServletRequest request, HttpServletResponse response) throws NoSuchAlgorithmException, IOException {
        logger.info("码支付回调2...");
        SystemWeb web = webConfigService.find_by_id(1L);
        PrintWriter writer = response.getWriter();
        Map<String, String> params = new HashMap<String, String>();
        Map<String, String[]> requestParams = request.getParameterMap();
        String valueStr = "";
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
            String name = iter.next();
            String[] values = requestParams.get(name);
            valueStr = values[0];
            params.put(name, valueStr);
        }
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);
        String prestr = "";
        String sign = params.get("sign");
        for (int i = 0; i < keys.size(); i++) {
            String key_name = keys.get(i);
            String value = params.get(key_name);
            if (value == null || value.equals("") || key_name.equals("sign")) {
                continue;
            }
            if (prestr.equals("")) {
                prestr = key_name + "=" + value;
            } else {
                prestr = prestr + "&" + key_name + "=" + value;
            }
        }
        String pay_no = request.getParameter("pay_no");// 流水号
        String pay_id = request.getParameter("pay_id");// 用户唯一标识
        SystemOrder order = this.orderService.findOrderByOutOrderId(pay_id);
        if (order == null) {
            writer.write("fail");
            writer.flush();
            writer.close();
            return;
        }
        MessageDigest md = MessageDigest.getInstance("MD5");
        CodepayConfig code = codePayConfigService.find_by_id(order.getPayConnet());
        md.update((prestr + code.getPublicKeyMch()).getBytes());
        String mySign = new BigInteger(1, md.digest()).toString(16).toLowerCase();
        if (mySign.length() != 32) mySign = "0" + mySign;
        if (mySign.equals(sign) && pay_no != null && pay_id != null) {
            if (order.getStatus() != 2) {
                BigDecimal webPayStaff1;
                if (order.getOrderType() == 2) {
                    webPayStaff1 = new BigDecimal(0.0D);
                } else {
                    SystemUser user = this.userService.findUserById(order.getUid());
                    SystemVip vip = this.vipService.find_vip_by_uid(order.getUid());
                    if (order.getPayType() == 1) {
                        if (vip == null) {
                            webPayStaff1 = user.getPayStaffWxpay();
                        } else {
                            if (vip.getStatus() == 1) {
                                webPayStaff1 = user.getVipPayStaffWxpay();
                            } else {
                                webPayStaff1 = user.getPayStaffWxpay();
                            }
                        }
                    } else if (order.getPayType() == 2) {
                        if (vip == null) {
                            webPayStaff1 = user.getPayStaffAlipay();
                        } else {
                            if (vip.getStatus() == 1) {
                                webPayStaff1 = user.getVipPayStaffAlipay();
                            } else {
                                webPayStaff1 = user.getPayStaffAlipay();
                            }
                        }
                    } else {
                        if (vip == null) {
                            webPayStaff1 = user.getPayStaffQqpay();
                        } else {
                            if (vip.getStatus() == 1) {
                                webPayStaff1 = user.getVipPayStaffQqpay();
                            } else {
                                webPayStaff1 = user.getPayStaffQqpay();
                            }
                        }
                    }
                }
                BigDecimal total_fee = new BigDecimal(params.get("money"));
                BigDecimal sub = total_fee.multiply(webPayStaff1).setScale(2, 4);
                order.setPaid(total_fee);
                order.setStatus(2);
                order.setTradeStatus("TRADE_SUCCESS");
                order.setTradeNo(params.get("pay_no"));
                order.setPaidTime(new Date());
                order.setChangeSett(sub);
                order.setIsSett(0);
                this.orderService.updateOrder(order);
                //处理代理信息
                Long uid = order.getUid();
                if (uid != null) {
                    Integer orderType = order.getOrderType();
                    if (orderType != 4 && orderType != 5 && orderType != 2) {
                        SystemUser user = userService.findUserById(uid);
                        if (user != null) {
                            Long parent = user.getUserParent();
                            if (parent > 0) {
                                ProxyList proxy = proxyService.find_proxy_by_uid(parent);
                                if (proxy != null) {
                                    BigDecimal price = order.getPrice();
                                    BigDecimal scale = price.multiply(proxy.getStaff()).setScale(2, BigDecimal.ROUND_HALF_UP);
                                    ProxyRecord record = new ProxyRecord();
                                    record.setOptTime(new Date());
                                    record.setCreateTime(new Date());
                                    record.setChangeMoney(scale);
                                    record.setOrderId(order.getId());
                                    record.setOrderMoney(price);
                                    record.setSrcUid(uid);
                                    record.setUid(parent);
                                    proxyService.save_record(record);
                                    userBalnesChange.addUserBalnes(parent, scale);
                                }
                            }
                        }
                    }
                }
                if (order.getOrderType() == 2) {
                    order.setChangeSett(new BigDecimal("0.00"));
                    this.orderService.updateOrder(order);
                    logger.info("回调处理注册订单成功:" + order.getOutOrderId());
                } else if (order.getOrderType() == 4 && order.getChType() == 1) {
                    VipNotifyProcess process = new VipNotifyProcess(this.orderService, order.getId(), this.vipService, web.getVipMethod());
                    Thread thread = new Thread(process);
                    thread.setDaemon(true);
                    thread.start();
                    logger.info("回调处理会员购买/续费订单成功:" + order.getOutOrderId());
                } else {
                    BigDecimal final_money = total_fee.subtract(sub).setScale(2, 4);
                    boolean b = this.userBalnesChange.addUserBalnes(order.getUid(), final_money);
                    logger.info("回调处理:订单:" + order.getOutOrderId() + " 处理成功,金额:" + final_money.doubleValue() + " 手续费:" + sub.doubleValue() + " 状态:" + b);
                    Thread thread;
                    if (order.getOrderType() == 3) {
                        NotifyThread notifyThread = new NotifyThread(this.orderService, order.getId(), this.yiPayFunction);
                        thread = new Thread(notifyThread);
                        thread.setDaemon(true);
                        thread.start();
                    }
                    if (order.getChType() == 2) {
                        SystemPayConfig config1 = payConfigService.getPayConfig(1L);
                        WxpayConfig wx_pay_config = wxPayConfigService.find_by_id(config1.getTrWxpay());
                        AlipayConfig ali_pay_connfig = alipayConfigService.find_by_id(config1.getTrAlipay());
                        VipModePayProcess payProcess = new VipModePayProcess(this.orderService, this.userBalnesChange, this.settLementService, order.getId(), this.vipService, this.userService, web, this.wxPayFunctionPC, this.aliPayFunction, ali_pay_connfig, wx_pay_config);
                        thread = new Thread(payProcess);
                        thread.setDaemon(true);
                        thread.start();
                    }
                }
            }
            writer.write("success");
        } else {
            writer.write("fail");
        }
        writer.flush();
        writer.close();
    }

}
